package org.hongbo.springbootebsapi.config;


import lombok.extern.slf4j.Slf4j;
import org.hongbo.springbootebsapi.interceptor.AllowRespInfoNullInterceptor;
import org.hongbo.springbootebsapi.interceptor.ResponseResultInterceptor;
import org.hongbo.springbootebsapi.interceptor.TokenValidInterceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 登录配置
 */
@Configuration
@Slf4j
//WebMvcConfigurerAdapter在2.0.*中已作废，有WebMvcConfigurer，WebMvcConfigurationSupport两种方案。
//public class WebSecurityConfig extends WebMvcConfigurerAdapter{
public class WebSecurityConfig implements WebMvcConfigurer {
//public class WebSecurityConfig extends WebMvcConfigurationSupport {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebSecurityConfig.class);

    @Bean
    public SecurityInterceptor getSecurityInterceptor(){
        return new SecurityInterceptor();
    }

    /**
     * remove jsessionid from url on startup
     * @return
     */
    @Bean
    public ServletContextInitializer servletContextInitializer() {
        return servletContext -> {
            servletContext.setSessionTrackingModes(Collections.singleton(SessionTrackingMode.COOKIE));
            SessionCookieConfig sessionCookieConfig=servletContext.getSessionCookieConfig();
            sessionCookieConfig.setHttpOnly(true);
        };

    }

    @Autowired
    private ResponseResultInterceptor responseResultInterceptor;

    @Autowired
    private AllowRespInfoNullInterceptor allowRespInfoNullInterceptor;

    @Autowired
    private TokenValidInterceptor tokenValidInterceptor;

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    }


    @Override
    public void  addInterceptors(InterceptorRegistry registry){
        // 多个拦截器组成一个拦截器链
        // addPathPatterns 用于添加拦截规则
        // excludePathPatterns 用于排除拦截
        InterceptorRegistration addInterceptor = registry.addInterceptor(getSecurityInterceptor());

        String apiUri = "/**";

        List<String> execludePatterns = new ArrayList<>();
        execludePatterns.add("/signVerify");
        execludePatterns.add("/swagger-ui.html");
        execludePatterns.add("/swagger-resources/**");
        execludePatterns.add("/favicon.ico");
        execludePatterns.add("/**/*.html");
        execludePatterns.add("/**/*.css");
        execludePatterns.add("/**/*.js");

        //响应结果控制拦截
        registry.addInterceptor(responseResultInterceptor).addPathPatterns(apiUri);
        //token验证
        registry.addInterceptor(tokenValidInterceptor).addPathPatterns(apiUri).excludePathPatterns(execludePatterns);
        //允许职责信息为空拦截
        registry.addInterceptor(allowRespInfoNullInterceptor).addPathPatterns(apiUri).excludePathPatterns(execludePatterns);

    }



    private class SecurityInterceptor extends HandlerInterceptorAdapter {

        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            long startTime = System.currentTimeMillis();
            request.setAttribute("startTime",startTime);
            return super.preHandle(request, response, handler);
        }


        /**
         * controller 执行之后，且页面渲染之前调用
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                               ModelAndView modelAndView) throws Exception {
            if (modelAndView != null) {
                long startTime  = (long)request.getAttribute("startTime");
                long endTime = System.currentTimeMillis();
                request.setAttribute("handlingTime",(endTime - startTime));
            }
        }

        /**
         * 页面渲染之后调用，一般用于资源清理操作
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            super.afterCompletion(request, response, handler, ex);
        }
    }
}
